/**
 * 
 */
package com.estock.platform.http.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;


/**
 * @author richard
 *
 */
public class RequestUtil {
	
	public static final String MULTIPART = "multipart/";
	public static final String CHARSET_UTF8 = "UTF-8";
	public static final String CHARSET_GBK = "GBK";
	
    private static final String PARAMETER_SEPARATOR = "&";
    private static final String NAME_VALUE_SEPARATOR = "=";
    private static final String DEFAULT_CONTENT_CHARSET = CHARSET_UTF8;
    
    

    /**
     * Translates parameters into <code>application/x-www-form-urlencoded</code> String
     *
     * @param parameters parameters to encode
     * @param encoding   The name of a supported
     *                   <a href="../lang/package-summary.html#charenc">character
     *                   encoding</a>.
     * @return Translated string
     */
    public static String format(
        final Collection<? extends Map.Entry<String, Object>> parameters,
        final String encoding) {
        final StringBuilder result = new StringBuilder();
        for (final Map.Entry<String, Object> parameter : parameters) {
            String value = parameter.getValue() == null? null : String.valueOf(parameter.getValue());
            if (!isEmpty(parameter.getKey())
                && !isEmpty(value)) {
                final String encodedName = encode(parameter.getKey(), encoding);
                final String encodedValue = value != null ? encode(value, encoding) : "";
                if (result.length() > 0) {
                    result.append(PARAMETER_SEPARATOR);
                }
                result.append(encodedName);
                result.append(NAME_VALUE_SEPARATOR);
                result.append(encodedValue);
            }
        }
        return result.toString();
    }
    
    public static String encode(final String content, final String encoding) {
        try {
            return URLEncoder.encode(content,
                encoding != null ? encoding : CHARSET_UTF8);
        } catch (UnsupportedEncodingException problem) {
            throw new IllegalArgumentException(problem);
        }
    }
    
    public static String getAttribute(HttpServletRequest requst, String paramKey) {
    	Object value = requst.getAttribute(paramKey);
    	return value != null ? decode(String.valueOf(value), CHARSET_UTF8) : "";
    }

    public static String decode(final String content, final String decoding) {
        try {
            return URLDecoder.decode(content,
            		decoding != null ? decoding : CHARSET_UTF8);
        } catch (UnsupportedEncodingException problem) {
            throw new IllegalArgumentException(problem);
        }
    }
    
    /**
     * Read data from Input Stream and save it as a String of UTF-8 format.
     *
     * @param is InputStream to be read
     * @return String that was read from the stream
     */
    public static String saveStreamAsUTF8(InputStream is) throws IOException {
        return toString(is, CHARSET_UTF8);
    }
    
    /**
     * Read data from Input Stream and save it as a String of GBK format.
     *
     * @param is InputStream to be read
     * @return String that was read from the stream
     */
    public static String saveStreamAsGBK(InputStream is) throws IOException {
        return toString(is, CHARSET_GBK);
    }

    public static String toString(
        final InputStream is, final String defaultCharset) throws IOException {
        if (is == null) {
            throw new IllegalArgumentException("InputStream may not be null");
        }

        String charset = defaultCharset;
        if (charset == null) {
            charset = DEFAULT_CONTENT_CHARSET;
        }
        BufferedReader bufferedReader = 
        		new BufferedReader(new InputStreamReader(is, charset)); 
        StringBuilder sb = new StringBuilder();
        int l;
        try {
            char[] tmp = new char[4096];
            while ((l = bufferedReader.read(tmp)) != -1) {
                sb.append(tmp, 0, l);
            }
        } finally {
        	bufferedReader.close();
        }
        return sb.toString();
    }

    @SuppressWarnings("rawtypes")
	public static Object instantiateClassWithParameters(Class clazz, Class[] paramsTypes,
                                                        Object[] paramValues) throws Exception {

        try {
            if (paramsTypes != null && paramValues != null) {
                if (!(paramsTypes.length == paramValues.length)) {
                    throw new IllegalArgumentException("Number of types and values must be equal");
                }

                if (paramsTypes.length == 0 && paramValues.length == 0) {
                    return clazz.newInstance();
                }
                @SuppressWarnings({ "unchecked"})
				Constructor clazzConstructor = clazz.getConstructor(paramsTypes);
                return clazzConstructor.newInstance(paramValues);
            }
            return clazz.newInstance();

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }


    public static boolean isEmpty(String value) {
        return value == null || "".equals(value);
    }
    
    public static final class HttpMethod {
        public static final String POST = "POST";
        public static final String GET = "GET";
    }
    
    public static final class HeaderType {
        public static final String CONTENT_TYPE = "Content-Type";
        public static final String AUTHORIZATION = "Authorization";
    }
    
    public static final class ContentType {
        public static final String URL_ENCODED = "application/x-www-form-urlencoded";
        public static final String JSON = "application/json";
    }
    
}
